﻿#ifndef XVOBJECT_H
#define XVOBJECT_H


#include <QColor>

#include "BaseState.h"
#include "basedata.h"

namespace xvs {

enum EnumObjType    //对象类型
{
    ObjType_Attr,//枝干(端口)属性对象
    ObjType_Inst,//普通指令对象
    ObjType_Task,//任务对象

    ObjType_Widget,//控件对象
    ObjType_Form,//窗体对象

    ObjType_Module,//模块对象
    ObjType_Project,//工程对象
    ObjType_ProMgr,//工程管理对象
};

enum EnumAttrType   //属性类型
{
    AttrType_None,
    AttrType_In,//输入
    AttrType_Out//输出
};

enum EnumInstType   //指令类型
{
    InstType_Normal,//常规指令
    InstType_Group,//组合指令
    InstType_Link,//链接指令
};

class ISerializable//保存加载
{
public:
  virtual ~ISerializable() = default;

  virtual QJsonObject Save(const QString&) = 0;

  virtual void Load(QJsonObject &,const QString&) {}
};

class IExecuteable//执行
{
public:
    virtual ~IExecuteable() = default;

public:
    /**
     * @brief Init  指令对象执行前(初始化)调用
     * @return  0 = 成功;  <0 (-1) = 错误发生;
     */
    virtual int Init() { return 0; }

    /**
     * @brief Execute   指令对象执行
     * @return 返回0 成功;
     * @return 返回值小于0 错误，***该错误将导致流程执行停止，重大错误导致流程无法执行时刻设置成<0的值
     * @return 返回值大于0 正确,约定的按某种规则继续执行流程，多用于中断、跳出等指令
     */
    virtual int Execute() = 0;

    /**
     * @brief Stop  指令对象执行后(停止)调用
     * @return 0 = 成功;  <0 (-1) = 错误发生;
     */
    virtual int Stop() { return 0; }

    /**
     * @brief Editor    返回指令对象对应的编辑器(编辑器类型和属性EditorType有关)
     * @param parent    该编辑器的父对象
     * @return          编辑器
     */
    virtual XVWidget * Editor(QWidget* parent = nullptr) { Q_UNUSED(parent) return nullptr; }
};

class XVObjectData;

/**
 * @brief The XVObject class 对象基类
 * @property    Id          唯一标识
 * @property    ObjType     对象类型（属性、指令、任务、控件、窗体、模块、工程、工程管理）
 * @property    Name        名称  插件必须要设置
 * @property    Desc        描述(显示文本)    可借此实现多语言
 * @property    Icon        图标
 * @property    Tip         提示标签
 * @property    CanDelete   可设置是否可以被删除 false=不可删除
 * @property    Enable      可用(有效性)
 * @property    Expand      展开/收缩
 *
 */
class OBJLIB_EXPORT XVObject : public QObject , public ISerializable
{
    Q_OBJECT
public:
    XVObject();
    virtual ~XVObject();

public:
    virtual QJsonObject Save(const QString& path);

    virtual void Load(QJsonObject &json,const QString&path);

public:

//    void CloneObj(XVObject* copyObj)
//    {
//        if (copyObj == nullptr)
//            return;
//        copyObj->mName = mName;
//        copyObj->mDesc = mDesc;
//        copyObj->mObjType = mObjType;
//        copyObj->mIcon = mIcon;
//        copyObj->mTip = mTip;
//        copyObj->help = help;
//        copyObj->Author = Author;
//        //copyObj->mSelected = mSelected;
//        copyObj->resetFirstTime();
//    }


    /**
     * @brief IsFirst 判断是否第一次执行(该函数第二次被调用返回false)
     * @return  第一次调用返回true
     */
    bool IsFirst();
    /**
     * @brief ResetFirst 重置IsFirst
     */
    void ResetFirst();

    XVObject* ParentObj();//父对象
    void SetParentObj(XVObject* parentobj);//设置父对象

    QList<XVObject *> &ObjectList();//子对象列表

    QList<QString> ObjectNameList();//子对象名称列表

    int Count() const;//子对象数量

    /**
     * @brief Pos   当前对象在父对象中的位置
     * @return -1 父对象不存在
     * @return -2 父对象中不存在子对象(不可能-可抛异常)
     */
    int Pos() const;

    /**
     * @brief At    根据序号访问子对象
     * @param index
     * @return
     */
    XVObject* At(const int index);
    /**
     * @brief AtByDesc  根据描述文本来查找子对象(描述文本可解决多语言问题)
     * @param desc
     * @return
     * @note            指令对象(如果描述相同怎么办？)
     */
    XVObject* AtByDesc(const QString& desc);
    XVObject* AtByCode(const QString& code);

    /**
     * @brief Add   添加子对象
     * @param obj   obj为空会抛异常;obj未设置Name会抛异常; //Name如果重复会抛异常;(指令名称会相同，去除该项检测)
     * @param index 值为-1则添加至尾部; 其他则为插入;值超出列表范围则以-1处理;
     */
    void Add(XVObject* obj,int index = -1);

    /**
     * @brief Remove    移除子对象
     * @param obj
     * @note            移除完成会发送信号 signal_removeobj
     * @note            如果设置了canDelete(false),此时不能被删除
     * @note            Remove会删除obj的所有子对象，以及父对象中的位置
     */
    void Remove(XVObject* obj);

    /**
     * @brief Erase     移除子对象并删除
     * @param obj
     */
    void Erase(XVObject* obj);
    void Clear(bool bDelete = true);//清空

public:
    QUuid Id() const;
    void SetUid(const QString &id);

    EnumObjType ObjType();
    void SetObjType(EnumObjType type);

    QString Name() const;
    void SetName(const QString& name);

    QString Desc() const;
    void SetDesc(const QString& desc);

    QString Icon() const;
    void SetIcon(const QString& icon);

    QString Tip() const;
    void SetTip(const QString& tip);

    bool CanDelete() const;
    void SetCanDelete(const bool value);

    bool Enable() const;
    void SetEnable(const bool value);

    bool Expand() const;
    void SetExpand(const bool expand);

private:
    XVObjectData* d_ptr;
};

}


#endif // XVOBJECT_H
